//
//  JSCall.m
//  SwiftLua
//
//  Created by xiaerfei on 2019/7/22.
//  Copyright © 2019 xiaerfei. All rights reserved.
//

#import "JSCall.h"
#import <JavaScriptCore/JavaScriptCore.h>
#import <objc/runtime.h>
#import <dlfcn.h>


static JSContext *jsContext = nil;
static JSValue *jsFunction = nil;
void patched() {
    [jsFunction callWithArguments:nil];
}

void patch_init() {
    jsContext = [[JSContext alloc] init];
    jsContext[@"log"] = ^(NSString *message) {
        NSLog(@"%@", message);
    };
    
    jsContext[@"patch"] = ^(NSString *className, NSString *methodName, JSValue *func) {
        void *class = (__bridge void *)objc_getClass(className.UTF8String);
        void *raw_method_address = dlsym(RTLD_DEFAULT, methodName.UTF8String);
        if (!class || !raw_method_address) {
            NSLog(@"class or method note found!");
            return;
        }
        long offset = 0;
        for (long i=0; i<1024; i++) {
            if (*(long *)(class+i) == (long)raw_method_address) {
                offset = i;
                break;
            }
        }
        if (!offset) return;
        jsFunction = func;
        *(void **)(class+offset) = &patched;
    };
    
    jsContext[@"call"] = ^(NSString *methodName){
        void (*raw_method_address)(void) = dlsym(RTLD_DEFAULT, methodName.UTF8String);
        if (raw_method_address) {
            raw_method_address();
        }
    };
    
    [jsContext evaluateScript:@"\
     function callback(){\
     log('patched hehe1');\
     log('calling raw method:');\
     call('hehe1');\
     }\
     patch('SwiftLua.aclass', 'hehe1', callback);\
     "];
}


@implementation JSCall

@end
